package com.shawn.springboot.integeration.atomikos.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

/**
 * JTA 事务配置
 *
 * @author shawn
 */
@Configuration
public class AtomikosConfig {
    /**
     * 将 UserTransactionImp 对象注册为 Spring 的 Bean
     * UserTransactionImp 是 Atomikos 提供的实现了 UserTransaction 接口的类。在此方法中，我们可以对事务超时时间进行配置。
     */
    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    /**
     * 将 UserTransactionManager 对象注册为 Spring 的 Bean
     * UserTransactionManager 是 Atomikos 提供的管理事务资源的类。通过该方法，我们可以对事务管理器进行配置例如设置是否强制关闭。
     */
    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    /**
     * 将 JtaTransactionManager 对象注册为 Spring 的 Bean
     * JtaTransactionManager 是 Spring 提供的用于管理分布式事务的事务管理器。
     * 在这个方法中，我们将之前创建的 UserTransaction 和 TransactionManager 对象传递给 JtaTransactionManager 的构造函数，
     * 以便创建一个完全集成了 Atomikos 的事务管理器。
     */
    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();
        TransactionManager atomikosTransactionManager = atomikosTransactionManager();
        return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
    }
}